/**
 *
 */
package com.angel.io.processors.commands.impl;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;

import com.angel.io.descriptor.ExportFileProcessorDescriptor;
import com.angel.io.descriptor.ExportedFileDescriptor;
import com.angel.io.exceptions.InvalidFileAccessException;
import com.angel.io.exceptions.InvalidFileDataException;
import com.angel.io.processors.commands.exports.ExportFileProcessorCommand;
import com.angel.io.processors.commands.imports.ImportFileProcessorCommand;
import com.angel.io.processors.commands.imports.ImportRowProcessorCommand;
import com.angel.io.separator.ColumnSeparator;
import com.angel.io.type.rows.ExportRowFile;
import com.angel.io.type.rows.ImportRowFile;
import com.angel.io.type.rows.impl.ExcelRowFile;
import com.angel.io.type.rows.impl.HeaderRowFile;

/**
 * @author William
 *
 */
public class ExcelFileProcessorCommand implements ImportFileProcessorCommand, ExportFileProcessorCommand{

	private static final String EXCEL_FILE_EXTENSION = ".xls";
	private static final Logger LOGGER = Logger.getLogger(ExcelFileProcessorCommand.class);
	private HSSFWorkbook workbook;
	private ImportRowProcessorCommand command;

	public ExcelFileProcessorCommand(){
		super();
	}

	public ExcelFileProcessorCommand(ImportRowProcessorCommand command){
		super();
		this.command = command;
	}

	public List<ImportRowFile> processFile(Integer page) throws InvalidFileDataException{
		List<ImportRowFile> allRowFiles = new ArrayList<ImportRowFile>();;
		HSSFSheet sheet = this.workbook.cloneSheet(page);
		List<ImportRowFile> pageRowFiles = this.processPage(sheet);
		allRowFiles.addAll(pageRowFiles);
		return allRowFiles;
	}

	private List<ImportRowFile> processPage(HSSFSheet sheet){
		int lastRow = sheet.getLastRowNum() + 1;
		List<ImportRowFile> rowFiles = new ArrayList<ImportRowFile>();
		for(int i = 0; i < lastRow; i++){
			HSSFRow row = sheet.getRow(i);
			if(row != null){
				ImportRowFile rowFile = new ExcelRowFile(row);
				if(!rowFile.isEmpty()){
					LOGGER.info("Adding row [ Number: " + row.getRowNum() + " - Quantity Cols: " + rowFile.quantityColumns() + " ] at sheet [Index: " + this.workbook.getSheetIndex(sheet) + " - Name: "+ this.workbook.getSheetName(this.workbook.getSheetIndex(sheet)) + "].");
					rowFiles.add(rowFile);
				} else {
					LOGGER.warn("Row [ Number: " + i + " ] at sheet [Index: " + this.workbook.getSheetIndex(sheet) + " - Name: "+ this.workbook.getSheetName(this.workbook.getSheetIndex(sheet)) + "] was ignored because it is EMPTY.");
				}
			} else {
				LOGGER.warn("Row [ Number: " + i + " ] at sheet [Index: " + this.workbook.getSheetIndex(sheet) + " - Name: "+ this.workbook.getSheetName(this.workbook.getSheetIndex(sheet)) + "] was ignored because it is null.");
			}
		}
		return rowFiles;
	}

	/**
	 * @return the command
	 */
	public ImportRowProcessorCommand getCommand() {
		return command;
	}

	/**
	 * @param command the command to set
	 */
	public void setCommand(ImportRowProcessorCommand command) {
		this.command = command;
	}

	public void finish(ExportedFileDescriptor exportedFileDescriptor, ExportFileProcessorDescriptor fileProcessorDescriptor, HeaderRowFile header, List<ExportRowFile> exportRows) {
		try {
			OutputStream outputStream = fileProcessorDescriptor.createOutputStream(exportedFileDescriptor, this.getFileExtension());
			this.workbook.write(outputStream);
			outputStream.close();
		} catch (IOException e) {
			throw new InvalidFileAccessException("IO error ocurred when finish output stream. ", e);
		}
	}

	public void initialize(InputStream inputStream) throws InvalidFileDataException {
		try {
			this.workbook = new HSSFWorkbook(new POIFSFileSystem(inputStream));
		} catch (IOException e) {
			throw new InvalidFileDataException(e);
		}
	}

	public void initialize() {
			this.workbook = new HSSFWorkbook();
	}

	public List<ExportRowFile> prepareFile(HeaderRowFile header, Integer quantityRows, ColumnSeparator columnSeparator){
		HSSFSheet sheet = this.workbook.getSheetAt(0);
		List<ExportRowFile> rowFiles = new ArrayList<ExportRowFile>();
		for(int i = 0; i < quantityRows + 1; i++){
			HSSFRow row = sheet.createRow(i + 1);
			ExportRowFile rowFile = new ExcelRowFile(row);
			rowFiles.add(rowFile);
		}
		return rowFiles;
	}

	public ExportRowFile createHeader(HeaderRowFile header, ColumnSeparator columnSeparator) {
		HSSFSheet sheet = this.workbook.createSheet();
		ExportRowFile exportHeader = new ExcelRowFile(sheet.createRow(0));
		for(int i = 0; i < header.quantityColumns().intValue(); i++){
			String columnName = header.getColumnName(i);
			exportHeader.addStringValue(columnName, header.getColumnPosition(columnName));
		}
		return exportHeader;
	}

	public void finish() {
		// Do nothing.
	}

	public String getFileExtension() {
		return EXCEL_FILE_EXTENSION;
	}

}
